////////////////////////////////////////////////////////////////////////
//
// Amuse Engine SDK - geometry/mesh
// Copyright( c) 2015.  All Rights Reserved
//
// File:		AEBaseSubmesh.h
// Author:		Gianluca Belardelli
// Date:		30/04/2015
//
/////////////////////////////////////////////////////////////////////////
#ifndef _AEBASESUBMESH_H_
#define _AEBASESUBMESH_H_

/// \brief La classe rappresenta un sottoinsieme di una Mesh.
/// Le Submesh sono parti di una Mesh e possono avere un singolo materiale ed
/// eventualmente una singola Lighmap. Ogni Submesh dovrebbe essere renderizzabile
/// utilizzando una singola chiamata Draw delle API grafiche, e pu&ograve; referenziare
/// fino ad un massimo di 32767 vertici nell'istanza della Mesh.
/// Scrivere dati nella Submesh &egrave; richiesto sono quando la Mesh &egrave;
/// creata da codice.
class AEBaseSubmesh
{
// Members
public:
	AEBoundingBox	m_bbBoundingBox;

	AEINT32			m_nRenderFirstIndex;
	AEINT32			m_nRenderNumIndices;
	AEINT32			m_nRenderFirstVertex;
	AEINT32			m_nRenderNumVertices;

	AEBaseMesh		*m_lpMesh;

	AEINT16			m_sGeometryInfoIndex;

protected:
	AEMaterial		*m_lpMaterial;
	AEINT16			m_sMaterialIndex;

// Methods
private:
	// Non-copyable
	AEBaseSubmesh( const AEBaseSubmesh &mesh );
	AEBaseSubmesh& operator=( const AEBaseSubmesh &mesh );

protected:
	AEBaseSubmesh( void );

public:
	AE_DECLARE_PLACEMENT_ALLOCATOR();

	/// \brief Distruttore.
	virtual ~AEBaseSubmesh( void );

	/// \brief Imposta il BoundingBox di questa Submesh. Richiesto solo quando
	/// la Submesh &egrave; creata da codice.
	/// \param bbBox BoundingBox che contiene la Submesh.
	AE_FORCEINLINE void SetBoundingBox( const AEBoundingBox &bbBox );

	/// \brief Ritorna il BoundingBox di questa Submesh.
	/// \return Un oggetto di tipo AEBoundingBox.
	AE_FORCEINLINE const AEBoundingBox &GetBoundingBox( void ) const;

	/// \brief Specifica il range di indici da renderizzare presenti nell'Index Buffer
	/// della Mesh. Per primitive grafiche non indicizzate i parametri sono da intendere
	/// relativi ai vertici.
	/// \param nStart Indice iniziale all'interno dell'Index Buffer.
	/// \param nNumIndices Numero di indici da utilizzare per il rendering.
	AE_FORCEINLINE void SetRenderRange( AEINT32 nStart, AEINT32 nNumIndices );

	/// \brief Ritorna il range di indici da renderizzare presenti nell'Index Buffer
	/// della Mesh
	/// \param nStart [out] Indice iniziale all'interno dell'Index Buffer.
	/// \param nNumIndices [out] Numero di indici da utilizzare per il rendering.
	AE_FORCEINLINE void GetRenderRange( AEINT32 &nStart, AEINT32 &nNumIndices ) const;

	/// \brief Specifica il range di vertici da renderizzare presenti nel Vertex Buffer
	/// della Mesh.
	/// \param nStart Vertice iniziale all'interno del Vertex Buffer.
	/// \param nNumVertices Numero di vertici da utilizzare per il rendering.
	AE_FORCEINLINE void SetRenderVertexRange( AEINT32 nStart, AEINT32 nNumVertices );

	/// \brief Ritorna il range di vertici da renderizzare presenti nel Vertex Buffer
	/// della Mesh.
	/// \param nStart [out] Indice iniziale all'interno del Vertex Buffer.
	/// \param nNumVertices [out] Numero di vertici da utilizzare per il rendering.
	AE_FORCEINLINE void GetRenderVertexRange( AEINT32 &nStart, AEINT32 &nNumVertices ) const;

	/// \brief Ritorna la Mesh della quale fa parte questa Submesh.
	/// \return Un puntatore ad un oggetto di tipo AEBaseMesh contenente la Mesh padre.
	AE_FORCEINLINE AEBaseMesh *GetBaseRenderMesh( void ) const;

	/// \brief Imposta la Mesh della quale fa parte questa Submesh.
	/// \param lpMesh Un puntatore ad un oggetto di tipo AEBaseMesh contenente la Mesh padre.
	AE_FORCEINLINE void SetMesh( AEBaseMesh *lpMesh );

	/// \brief Associates a submesh with a material (surface) so that every instance of this submesh is rendered with this material setup.
	/// To replace a material inside the mesh's material palette, rather use function VBaseMesh::SetSurface
	/// \param pSurface
	///   The surface to set
	/// \param iMaterialIndex
	///   The index of the passed surface within the material table of the owner mesh. The index must be in valid range [0..pMesh->GetSurfaceCount()-1]
	AE_FORCEINLINE void SetMaterial( AEMaterial *lpMaterial, AEINT16 sMaterialIndex );

	/// \brief
	///   Returns the submesh's material (surface).
	AE_FORCEINLINE AEMaterial *GetMaterial( void ) const;

	/// \brief
	///   Returns the index of the material in the owner mesh's material list
	AE_FORCEINLINE AEINT32 GetMaterialIndex( void ) const;
};

#include "AEBaseSubmesh.inl"

#endif // _AEBASESUBMESH_H_
